package cn.iocoder.yudao.module.member.service.order;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.member.controller.admin.siteconfig.vo.SiteConfigurationVo;
import cn.iocoder.yudao.module.member.controller.admin.siteconfig.vo.SysLinkVo;
import cn.iocoder.yudao.module.member.controller.app.order.vo.*;
import cn.iocoder.yudao.module.member.dal.dataobject.order.MemberCertificateOrderDo;
import cn.iocoder.yudao.module.member.dal.mysql.order.MemberCertificateOrderMapper;
import cn.iocoder.yudao.module.member.dal.redis.no.OrderNoRedisDAO;
import cn.iocoder.yudao.module.member.enums.SysFlagEnum;
import cn.iocoder.yudao.module.member.service.siteconfiguration.SiteConfigurationService;
import com.dd.plist.NSDictionary;
import com.dd.plist.PropertyListParser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.cms.CMSSignedData;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;

@Slf4j
@Service
public class HuaYangV2Strategy implements SysLinkStrategy{

    private final String SITE_CONFIG_CACHE_TOKEN = "SITE:CONFIG:CACHE:TOKEN";
    //B系统调用A系统的接口（秒出和预约）
    private final String B_To_A = "/api/v1/public/device/add";

    private final String GETBYID = "/api/v1/public/device/get";

    private final String mplist = "/api/v1/public/device/backup-mp";

    private final String changeMp = "/api/v1/public/device/change-mp";

    private final String SITE_CONFIG_CACHE_MAIN_URL = "SITE:CONFIG:CACHE:MAIN:URL";
    @Resource
    private FileApi fileApi;
    @Resource
    private OrderNoRedisDAO orderNoRedisDAO;
    @Resource
    private SiteConfigurationService siteConfigurationService;
    @Resource
    private MemberCertificateOrderMapper memberCertificateOrderMapper;

   @Override
    public MemberCertificateOrderDo createOrder(AppMemberCertificateOrderVo appOrderVo) {
        String token = orderNoRedisDAO.getValue(SITE_CONFIG_CACHE_TOKEN);
        String mainUrl = orderNoRedisDAO.getValue(SITE_CONFIG_CACHE_MAIN_URL);
        String deviceType  = "iphone";
        if ("ipad".equals(appOrderVo.getDeviceType())){
             deviceType  = "ipad";
        }
        MemberCertificateOrderDo  returnDo = BeanUtils.toBean(appOrderVo,MemberCertificateOrderDo.class);
        log.info("调用华阳生成设备信息udid={}设备订单号={}时间={}",appOrderVo.getUdid(),appOrderVo.getCertificateOrderCode(), DateUtil.now()) ;
        StopWatch stopWatch = new StopWatch("调用华阳生成设备信息");
        try {
            HttpResponse execute = null;
            //判断是秒出还是预约
            stopWatch.start("调用华阳生成设备信息开始");
             try {
                    String force = StringUtils.isEmpty(appOrderVo.getForce())?"0":appOrderVo.getForce();
                    Map<String ,Object> requestParams = new HashMap();
                    requestParams.put("is_book",0);
                    requestParams.put("udid",appOrderVo.getUdid());
                    requestParams.put("pool",appOrderVo.getPoolType());
                    requestParams.put("warranty",0);
                    requestParams.put("device_type",deviceType);
                    requestParams.put("note",appOrderVo.getUserName());
                    requestParams.put("force",force);
                    requestParams.put("token",token);
                    execute = HttpUtil.createPost(mainUrl + B_To_A)
                            .body(JSONUtil.toJsonStr(requestParams))
                            .timeout(40000).execute();
                }catch (HttpException e){
                 System.err.println("HTTP异常: " + e.getMessage());
             }

            log.info("调用华阳生成设备信息结束");
            stopWatch.stop();
                if (!execute.isOk()){
                    throw exception(MAIN_URL_ERROR);
                }
                String adoResultString = JSONUtil.toJsonStr(execute.body());
                RequestSysVo<HauYangThirdReturnVo> adoResult = JSONUtil.toBean(adoResultString ,RequestSysVo.class);
                if (1 == adoResult.getCode() || 0 == adoResult.getCode()){
                    log.info("系统创建设备返回日志信息{}",adoResult.getData());
                    HauYangV2ThirdReturnVo hauYangV2ThirdReturnVo = JSONUtil.toBean(JSONUtil.toJsonStr(adoResult.getData()), HauYangV2ThirdReturnVo.class);
                    stopWatch.start("P12转换开始");
                    if (ObjectUtil.isNotEmpty(hauYangV2ThirdReturnVo.getP12())){
                        File tempFileP12 = FileUtil.createTempFile(".p12", false);
                        String fileName = UUID.fastUUID() + "." + FileUtil.getSuffix(tempFileP12);
                        String file =null;
                        try {
                            // 1. Base64解码
                            byte[] p12Bytes = Base64.getDecoder().decode(hauYangV2ThirdReturnVo.getP12().replaceAll("\\s", ""));
                            // 2. 写入文件
                            FileOutputStream fos = new FileOutputStream(tempFileP12);
                            try {
                                fos.write(p12Bytes);
                            }catch (IOException e){
                                log.info("p12文件写入异常{}",e.getMessage());
                                e.printStackTrace();
                            }finally {
                                fos.close();
                            }
                            // 3. 验证证书（可选）
                            KeyStore ks = KeyStore.getInstance("PKCS12");
                            char[] password = "1".toCharArray(); // 如果有密码在此处设置
                            try (InputStream is = FileUtil.getInputStream(Paths.get(tempFileP12.toURI()))) {
                                ks.load(is, password);
                            }
                            System.out.println("证书类型: " + ks.getType());
                            System.out.println("证书别名: " + ks.aliases().nextElement());
                            System.out.println("P12文件生成成功: " + fileName);
                            file =  fileApi.createFile(fileName, "p12", FileUtil.readBytes(tempFileP12));
                            log.info("p12路径"+file);

                            hauYangV2ThirdReturnVo.setP12(file);
                        } catch (Exception e) {
                            log.error("文件转换失败"+e.getMessage());
                            e.printStackTrace();
                        }

                    }
                    stopWatch.stop();
                    stopWatch.start("描述文件转换开始");
                    if (ObjectUtil.isNotEmpty(hauYangV2ThirdReturnVo.getMobileprovision())){
                        File tempFile = FileUtil.createTempFile(".mobileprovision", false);
                        String fileName = UUID.fastUUID() + "." + FileUtil.getSuffix(tempFile);
                        byte[] mpBytes = Base64.getDecoder().decode(hauYangV2ThirdReturnVo.getMobileprovision().replaceAll("\\s", ""));
                        // 2. 写入文件
                        FileOutputStream fosmp = new FileOutputStream(tempFile);
                        try {
                            fosmp.write(mpBytes);
                        }catch (IOException e){
                            log.info("描述文件写入异常{}",e.getMessage());
                            e.printStackTrace();
                        }finally {
                            fosmp.close();
                        }
                        // 解析CMS格式
                        CMSSignedData signedData = new CMSSignedData(mpBytes);
                        byte[] content = (byte[]) signedData.getSignedContent().getContent();

                        // 解析plist内容
                        NSDictionary rootDict = (NSDictionary) PropertyListParser.parse(content);
                        hauYangV2ThirdReturnVo.setName(rootDict.get("TeamName").toString());
                        log.info("描述文件创建成功");
                        String file =  fileApi.createFile(fileName, "mb", FileUtil.readBytes(tempFile));
                        hauYangV2ThirdReturnVo.setMobileprovision(file);
                    }
                    stopWatch.stop();
                    returnDo.setUdid(appOrderVo.getUdid());
                    returnDo.setCerName(hauYangV2ThirdReturnVo.getName());
                    returnDo.setSysIdString(hauYangV2ThirdReturnVo.getId());
                    returnDo.setP12Url(hauYangV2ThirdReturnVo.getP12());
                    returnDo.setMpUrl(hauYangV2ThirdReturnVo.getMobileprovision());
                    returnDo.setDropFlag(Boolean.FALSE) ;
                    returnDo.setP12Password("1");
                    log.info(stopWatch.prettyPrint());
                    return returnDo;
                }else {
                    log.info("系统返回日志信息{}{}",MAIN_URL_EXCEPTION,adoResult.getMsg());
                    throw new RuntimeException(adoResult.getMsg());
                }
            //调用登录接口
        }catch (Exception e){
            log.info("系统返回日志信息{}",e.getMessage());
            throw exception(MAIN_URL_EXCEPTION,e.getMessage());
        }
    }

    @Override
    public String getSysType() {
        return SysFlagEnum.HUA_YANG_V2.getType();
    }

    @Override
    public AppMemberCertificateOrderVo getById(MemberCertificateOrderDo memberCertificateOrderDO) {

        SiteConfigurationVo config = siteConfigurationService.getConfig();
        SysLinkVo sysLinkVo = config.getSysLinkVos().stream().filter(t -> t.getMainUrl().equals(memberCertificateOrderDO.getMainUrl())).findFirst().orElse(null);
        log.info("对应得配置信息"+JSONUtil.toJsonStr(sysLinkVo));
        String token = null;
        if (sysLinkVo != null) {
            token = sysLinkVo.getToken();
        }else {
            throw exception(MAIN_URL_ERROR);
        }
        String mainUrl = memberCertificateOrderDO.getMainUrl();
        AppMemberCertificateOrderVo returnVo = new AppMemberCertificateOrderVo();
        StopWatch stopWatch = new StopWatch("调用华阳查询设备信息");
        try {
            stopWatch.start("调用接口");
                HttpResponse execute = HttpUtil.createPost( mainUrl+GETBYID+"?"+"token="+token+"&cert_id="+memberCertificateOrderDO.getCerId()+"&udid="+memberCertificateOrderDO.getUdid()).execute();
                if (!execute.isOk()){
                    throw exception(MAIN_URL_ERROR);
                }
            stopWatch.stop();
                String adoResultString = JSONUtil.toJsonStr(execute.body());
                RequestSysVo<HauYangThirdReturnVo> adoResult = JSONUtil.toBean(adoResultString ,RequestSysVo.class);
                if (1 == adoResult.getCode() || 0 == adoResult.getCode()){
                    log.info("系统创建设备返回日志信息{}",adoResult.getData());
                    HauYangV2ThirdReturnVo hauYangV2ThirdReturnVo = JSONUtil.toBean(JSONUtil.toJsonStr(adoResult.getData()), HauYangV2ThirdReturnVo.class);
                    stopWatch.start("p12文件写入");
                        if (ObjectUtil.isNotEmpty(hauYangV2ThirdReturnVo.getP12())) {
                            File tempFileP12 = FileUtil.createTempFile(".p12", false);
                            String fileName = UUID.fastUUID() + "." + FileUtil.getSuffix(tempFileP12);
                            String file = null;
                            try {
                                // 1. Base64解码
                                byte[] p12Bytes = Base64.getDecoder().decode(hauYangV2ThirdReturnVo.getP12().replaceAll("\\s", ""));
                                // 2. 写入文件
                                try (FileOutputStream fos = new FileOutputStream(tempFileP12)) {
                                    fos.write(p12Bytes);
                                }
                                // 3. 验证证书（可选）
                                KeyStore ks = KeyStore.getInstance("PKCS12");
                                char[] password = "1".toCharArray(); // 如果有密码在此处设置
                                try (InputStream is = FileUtil.getInputStream(Paths.get(tempFileP12.toURI()))) {
                                    ks.load(is, password);
                                }
                                System.out.println("证书类型: " + ks.getType());
                                System.out.println("证书别名: " + ks.aliases().nextElement());
                                System.out.println("P12文件生成成功: " + fileName);
                                file = fileApi.createFile(fileName, "p12", FileUtil.readBytes(tempFileP12));
                                log.info("p12路径" + file);

                                hauYangV2ThirdReturnVo.setP12(file);
                            } catch (Exception e) {
                                log.error("文件转换失败" + e.getMessage());
                                e.printStackTrace();
                            }
                        }
                        stopWatch.stop();
                    stopWatch.start("描述文件写入");
                    if (ObjectUtil.isNotEmpty(hauYangV2ThirdReturnVo.getMobileprovision())){
                        File tempFile = FileUtil.createTempFile(".mobileprovision", false);
                        byte[] mpBytes = Base64.getDecoder().decode(hauYangV2ThirdReturnVo.getMobileprovision().replaceAll("\\s", ""));
                        // 2. 写入文件
                        try (FileOutputStream fos = new FileOutputStream(tempFile)) {
                            fos.write(mpBytes);
                        }
                        // 解析CMS格式
                        CMSSignedData signedData = new CMSSignedData(mpBytes);
                        byte[] content = (byte[]) signedData.getSignedContent().getContent();

                        // 解析plist内容
                        NSDictionary rootDict = (NSDictionary) PropertyListParser.parse(content);
                        hauYangV2ThirdReturnVo.setName(rootDict.get("TeamName").toString());
                        log.info("描述文件创建成功");
                        String fileName = UUID.fastUUID() + "." + FileUtil.getSuffix(tempFile);
                        String file =  fileApi.createFile(fileName, "mb", FileUtil.readBytes(tempFile));
                        hauYangV2ThirdReturnVo.setMobileprovision(file);
                    }
                    stopWatch.stop();
                    returnVo.setP12Url(hauYangV2ThirdReturnVo.getP12());
                    returnVo.setMpUrl(hauYangV2ThirdReturnVo.getMobileprovision());
                    returnVo.setDropFlag(hauYangV2ThirdReturnVo.getState());
                    returnVo.setCerName(hauYangV2ThirdReturnVo.getName());
                    log.info(stopWatch.prettyPrint());
                    return returnVo;
                }else {
                    log.info("系统返回日志信息{}{}",MAIN_URL_EXCEPTION,adoResult.getMsg());
                    throw new RuntimeException(adoResult.getMsg());
                }
        }catch (Exception e){
            log.info("系统返回日志信息{}",e.getMessage());
            throw exception(MAIN_URL_EXCEPTION,e.getMessage());
        }
    }


    public List<HauYangMpThirdReturnVo> listMp(MemberCertificateOrderDo memberCertificateOrderDo){
        // 前端接口 deviceId是空的
        HttpResponse execute = null;
        try {
            String mainUrl = orderNoRedisDAO.getValue(SITE_CONFIG_CACHE_MAIN_URL);
            String token = orderNoRedisDAO.getValue(SITE_CONFIG_CACHE_TOKEN);
            StopWatch stopWatch = new StopWatch("调用华阳获取描述文件");
            stopWatch.start("调用华阳获取描述文件开始");
            execute= HttpUtil.createPost(mainUrl + mplist+"?"+"udid="+memberCertificateOrderDo.getUdid()+"&device_id="+memberCertificateOrderDo.getSysIdString()
                            +"&only_bid=1&token="+token)
                    .header("Content-Type","multipart/form-data").timeout(40000).execute();
            stopWatch.stop();
            if (!execute.isOk()){
                throw exception(MAIN_URL_ERROR);
            }
            String resultString = JSONUtil.toJsonStr(execute.body());
            RequestSysVo<List<HauYangMpThirdReturnVo>> result = JSONUtil.toBean(resultString ,RequestSysVo.class);
            if (1 == result.getCode() || 0 == result.getCode()) {
                log.info("获取描述文件列表返回日志信息{}", result.getData());
                return result.getData();
            }else {
                log.info("系统返回日志信息{}{}",MAIN_URL_EXCEPTION,result.getMessage());
                throw new RuntimeException(result.getMessage());
            }
        }catch (HttpException e){
            if (execute != null && execute.getStatus() == 504) { // HTTP状态码504表示网关超时
                System.err.println("请求超时");
                throw exception(THREAD_ERROR_CODE);
            }else {
                log.info("系统返回日志信息{}",e.getMessage());
                throw exception(MAIN_URL_ERROR);
            }
        }
    }

    public void changeMp(MemberCertificateOrderDo memberCertificateOrderDo,String bundleId){
        HttpResponse execute = null;
        HttpResponse execute2 = null;
        try {
            String mainUrl = orderNoRedisDAO.getValue(SITE_CONFIG_CACHE_MAIN_URL);
            String token = orderNoRedisDAO.getValue(SITE_CONFIG_CACHE_TOKEN);
            StopWatch stopWatch = new StopWatch("调用华阳切换描述文件");
            stopWatch.start("调用华阳切换描述文件开始");
            execute= HttpUtil.createPost(mainUrl + changeMp+"?"+"udid="+memberCertificateOrderDo.getUdid()+"&device_id="+memberCertificateOrderDo.getSysIdString()
                            +"&bundle_id="+bundleId+"&token="+token)
                    .header("Content-Type","multipart/form-data").timeout(40000).execute();
            stopWatch.stop();
            if (!execute.isOk()){
                throw exception(MAIN_URL_ERROR);
            }
            String resultString = JSONUtil.toJsonStr(execute.body());
            RequestSysVo result = JSONUtil.toBean(resultString ,RequestSysVo.class);
            if (1 == result.getCode() || 0 == result.getCode()) {
                log.info("切换描述文件成功，返回日志信息{}", result.getData());
                log.info("开始将切换的描述文件上传到本地");
                stopWatch.start("调用华阳描述文件本地化开始");
                execute2 = HttpUtil.createPost( mainUrl+GETBYID+"?"+"token="+token+"&cert_id="+
                        memberCertificateOrderDo.getCerId()+"&udid="+memberCertificateOrderDo.getUdid()).execute();
                if (!execute2.isOk()){
                    throw exception(MAIN_URL_ERROR);
                }
                stopWatch.stop();
                String adoResultString = JSONUtil.toJsonStr(execute2.body());
                RequestSysVo<HauYangThirdReturnVo> adoResult = JSONUtil.toBean(adoResultString ,RequestSysVo.class);
                if (1 == adoResult.getCode() || 0 == result.getCode()){
                    stopWatch.start("描述文件写入");
                    HauYangV2ThirdReturnVo hauYangV2ThirdReturnVo = JSONUtil.toBean(JSONUtil.toJsonStr(adoResult.getData()), HauYangV2ThirdReturnVo.class);
                    if (ObjectUtil.isNotEmpty(hauYangV2ThirdReturnVo.getMobileprovision())){
                        File tempFile = FileUtil.createTempFile(".mobileprovision", false);
                        byte[] mpBytes = Base64.getDecoder().decode(hauYangV2ThirdReturnVo.getMobileprovision().replaceAll("\\s", ""));
                        // 2. 写入文件
                        try (FileOutputStream fos = new FileOutputStream(tempFile)) {
                            fos.write(mpBytes);
                            // 解析CMS格式
                            CMSSignedData signedData = new CMSSignedData(mpBytes);
                            byte[] content = (byte[]) signedData.getSignedContent().getContent();

                            // 解析plist内容
                            NSDictionary rootDict = (NSDictionary) PropertyListParser.parse(content);
                            String fileName = UUID.fastUUID() + "." + FileUtil.getSuffix(tempFile);
                            String file =  fileApi.createFile(fileName, "mb", FileUtil.readBytes(tempFile));
                            log.info("描述文件创建成功");
                            memberCertificateOrderMapper.updateMpUrl(memberCertificateOrderDo.getId(),file,rootDict.get("TeamName").toString());
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }
                    stopWatch.stop();
                }
            }else {
                log.info("切换描述文件失败，错误信息为{}{}",MAIN_URL_EXCEPTION,result.getMessage());
                throw new RuntimeException(result.getMessage());
            }

        }catch (HttpException e){
            log.info("切换描述文件失败{}",e.getMessage());
        }
    }

}
